package com.gitee.wsl.common.ui.ext.color

import androidx.compose.ui.graphics.Color
import com.gitee.wsl.common.ui.theme.local.EncodedColors
import com.gitee.wsl.mathematics.function.scale.continuous.SequentialScale
import com.gitee.wsl.mathematics.function.scale.continuous.linear.LinearScale
import com.gitee.wsl.mathematics.function.scale.discrete.OrdinalScale

val Color.Companion.scalesChromatic get() = ScalesChromatic

/**
 * Access the data2viz collection of chromatic scales.
 * To create a non-color scale use Scales instead.
 * Available factories:
 *
 * ScalesChromatic
 *      Continuous              (continuous color scales with pre-configured interpolators)
 *          -> linearRGB
 *          -> linearLAB
 *          -> linearHSL
 *          -> ...
 *      Sequential              (continuous color scales with pre-configured interpolators and color scheme)
 *          SingleHue               (will scale over a single hue ie. white -> blue)
 *              -> blues
 *              -> greens
 *              -> ...
 *          MultiHue                (convergent scales with multiple hues ie. blue -> green)
 *              -> viridis
 *              -> plasma
 *              -> blue_green
 *              -> ...
 *          Diverging               (divergent scales with multiple hues ie. blue -> white -> red for temperature)
 *              -> pink_green
 *              -> red_blue
 *              -> ...
 *          Cyclical                (these color scales cycle: start color = end color)
 *              -> rainbow
 *              -> sinebow
 *      Discrete                (contrasted color scheme for discrete domain scales)
 *          -> category10
 *          -> accent8
 *          -> paired12
 *          -> ...
 */
 object ScalesChromatic {

     object Continuous {
         fun linearRGB(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(
             Color.Companion::rgbLinearInterpolator
         ).apply(init)
         fun defaultRGB(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(
             Color.Companion::rgbDefaultInterpolator
         ).apply(init)
       /*  fun linearLAB(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(Interpolate.Companion::labInterpolator).apply(init)
         fun linearHCL(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(Interpolate.Companion::hclInterpolator).apply(init)
         fun linearHCLLong(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(Interpolate.Companion::hclLongInterpolator).apply(init)
         fun linearHSL(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(Interpolate.Companion::hslInterpolator).apply(init)
         fun linearHSLLong(init: LinearScale<Color>.() -> Unit = {}): LinearScale<Color> = LinearScale(Interpolate.Companion::hslLongInterpolator).apply(init)
*/    }

    // TODO these scales should also be available as "ordinal scales"
     object Sequential {

         object SingleHue {
             fun blues(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.blues9.colors)).apply(init)

             fun greens(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.greens9.colors)).apply(init)

             fun greys(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.greys9.colors)).apply(init)

             fun oranges(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.oranges9.colors)).apply(init)

             fun purples(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.purples9.colors)).apply(init)

             fun reds(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.reds9.colors)).apply(init)
        }

        // TODO warm, cool, cubehelix
        // TODO YlOrBr, YlOrRd
         object MultiHue {
             fun viridis(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.viridis.colors)).apply(init)


             fun magma(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.magma.colors)).apply(init)

             fun inferno(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.inferno.colors)).apply(init)

             fun plasma(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.plasma.colors)).apply(init)

             fun blue_green(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.BuGN9.colors)).apply(init)

             fun blue_purple(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.BuPu9.colors)).apply(init)

             fun green_blue(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.GnBu9.colors)).apply(init)

             fun orange_red(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.OrRd9.colors)).apply(init)

             fun purple_blue(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.PuBu9.colors)).apply(init)

             fun purple_blue_green(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.PuBuGn9.colors)).apply(init)

             fun purple_red(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.PuRd9.colors)).apply(init)

             fun red_purple(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.RdPu9.colors)).apply(init)

             fun yellow_green(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.YlGn9.colors)).apply(init)

             fun yellow_green_blue(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.YlGnbU9.colors)).apply(init)

             fun yellow_green_brown(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.YlGnBr9.colors)).apply(init)

             fun yellow_green_red(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.YlGnRd9.colors)).apply(init)
        }

         object Diverging {
             fun brown_blueGreen(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.BrBG11.colors)).apply(init)

             fun pink_green(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.PiYG11.colors)).apply(init)

             fun purple_green(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.PRGn11.colors)).apply(init)

             fun purple_orange(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.PuOR11.colors)).apply(init)

             fun red_blue(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.RdBU11.colors)).apply(init)

             fun red_grey(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.RdGY11.colors)).apply(init)

             fun red_yellow_blue(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.RdYlBu11.colors)).apply(init)

             fun blue_yellow_red(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.BuYlRd11.colors)).apply(init)

             fun red_yellow_green(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.RdYlGn11.colors)).apply(init)

             fun spectral(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbBasisInterpolator(EncodedColors.spectral11.colors)).apply(init)
        }

        // TODO rainbow
         object Cyclical {
             fun sineBow(init: SequentialScale<Color>.() -> Unit = {}): SequentialScale<Color> =
                SequentialScale(Color.rgbSineBowInterpolator()).apply(init)
        }
    }

     object Discrete {
         fun <D> accent8(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.accents.colors).apply(init)

         fun <D> dark8(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.dark2.colors).apply(init)

         fun <D> paired12(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.paired.colors).apply(init)

         fun <D> pastel9(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.pastel1.colors).apply(init)

         fun <D> pastel8(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.pastel2.colors).apply(init)

         fun <D> vivid9(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.set1.colors).apply(init)

         fun <D> vivid8(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.set2.colors).apply(init)

         fun <D> pale12(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.set3.colors).apply(init)

         fun <D> category10(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.category10.colors).apply(init)

         fun <D> categoryA20(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.category20.colors).apply(init)

         fun <D> categoryB20(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.category20b.colors).apply(init)

         fun <D> categoryC20(init: OrdinalScale<D, Color>.() -> Unit = {}): OrdinalScale<D, Color> =
            OrdinalScale<D, Color>(EncodedColors.category20c.colors).apply(init)
    }
}